package com.duff.pdf.reader.library;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener;
import com.github.barteksc.pdfviewer.listener.OnPageChangeListener;
import com.github.barteksc.pdfviewer.listener.OnPageErrorListener;
import com.github.barteksc.pdfviewer.listener.OnPageScrollListener;
import com.github.barteksc.pdfviewer.listener.OnTapListener;
import com.github.barteksc.pdfviewer.scroll.DefaultScrollHandle;
import com.github.barteksc.pdfviewer.util.FitPolicy;

import java.io.File;

/**
 * author：duff
 * version：1.0.0
 * date：2018/1/28
 * desc：
 */
public class PdfReaderActivity extends AppCompatActivity implements View.OnClickListener, SeekBar.OnSeekBarChangeListener,
        OnPageChangeListener, OnLoadCompleteListener, OnPageErrorListener, OnTapListener, OnPageScrollListener {

    private static final String TAG = "PdfReader";

    private PDFView mPdfView;
    private View bg_top;
    private View bg_bottom;

    private View mTitleBar;
    private RelativeLayout rl_back;
    private TextView tv_title;

    private View mFooter;
    private RelativeLayout rl_last;
    private RelativeLayout rl_next;
    private SeekBar seekBar;
    private LinearLayout ll_send;
    private LinearLayout ll_rotate;
    private ImageView iv_rotate;
    private TextView tv_seek;
    private View errorLayout;

    public static final String SCHEME_FILE = "file";

    private String mPdfPath;
    private int mTotalPages = -1;

    private Handler mHandler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pdf_reader);
        initView();

        handleIntent(getIntent());
    }

    private void initView() {
        mPdfView = (PDFView) findViewById(R.id.pdfView);
        bg_top = findViewById(R.id.bg_top);
        bg_bottom = findViewById(R.id.bg_bottom);

        mTitleBar = findViewById(R.id.titleBar);
        rl_back = (RelativeLayout) findViewById(R.id.rl_back);
        tv_title = (TextView) findViewById(R.id.tv_title);

        mFooter = findViewById(R.id.footerLayout);
        rl_last = (RelativeLayout) findViewById(R.id.rl_last);
        rl_next = (RelativeLayout) findViewById(R.id.rl_next);
        seekBar = (SeekBar) findViewById(R.id.seek_bar);
        ll_send = (LinearLayout) findViewById(R.id.ll_send);
        ll_rotate = (LinearLayout) findViewById(R.id.ll_rotate);
        iv_rotate = (ImageView) findViewById(R.id.iv_rotate);
        tv_seek = (TextView) findViewById(R.id.tv_seek);
        errorLayout = findViewById(R.id.errorLayout);

        rl_back.setOnClickListener(this);
        rl_last.setOnClickListener(this);
        rl_next.setOnClickListener(this);
        ll_send.setOnClickListener(this);
        ll_rotate.setOnClickListener(this);

        seekBar.setOnSeekBarChangeListener(this);
    }

    private void hideTitleAndFooter() {
        int topHeight = mTitleBar.getHeight();
        int bottomHeight = mFooter.getHeight();
        AnimatorSet animatorSet = new AnimatorSet();
        ObjectAnimator topDriftY = ObjectAnimator.ofFloat(mTitleBar, "translationY", 0.0f, -topHeight);
        ObjectAnimator bottomDriftY = ObjectAnimator.ofFloat(mFooter, "translationY", 0.0f, bottomHeight);

        animatorSet.playTogether(topDriftY, bottomDriftY);
        animatorSet.setDuration(300);
        animatorSet.setInterpolator(new DecelerateInterpolator());
        animatorSet.start();
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                mTitleBar.setVisibility(View.INVISIBLE);
                mFooter.setVisibility(View.INVISIBLE);
            }
        });
    }

    private void showTitleAndFooter() {
        mTitleBar.setVisibility(View.VISIBLE);
        mFooter.setVisibility(View.VISIBLE);
        // animation
        int topHeight = mTitleBar.getHeight();
        int bottomHeight = mFooter.getHeight();
        AnimatorSet animatorSet = new AnimatorSet();
        ObjectAnimator topDriftY = ObjectAnimator.ofFloat(mTitleBar, "translationY", -topHeight, 0.0f);
        ObjectAnimator bottomDriftY = ObjectAnimator.ofFloat(mFooter, "translationY", bottomHeight, 0.0f);
        animatorSet.playTogether(topDriftY, bottomDriftY);
        animatorSet.setDuration(300);
        animatorSet.setInterpolator(new DecelerateInterpolator());
        animatorSet.start();
    }

    private void showErrorLayout() {
        TextView tv_error = (TextView) errorLayout.findViewById(R.id.tv_error);
        tv_error.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openPdfApplication();
            }
        });
        errorLayout.setVisibility(View.VISIBLE);
    }

    private void openPdfApplication() {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri uri = Uri.fromFile(new File(mPdfPath));
        intent.setDataAndType(uri, "application/pdf");
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        startActivity(intent);
    }

    private void handleIntent(Intent intent) {
        if (intent != null) {
            // 显示传递
            mPdfPath = intent.getStringExtra("pdf_path");
            if (!TextUtils.isEmpty(mPdfPath)) {
                displayPdfExternal(mPdfPath);
            } else {
                // 隐示传递
                Uri uri = intent.getData();
                if (uri != null && !TextUtils.isEmpty(uri.getScheme())) {
                    String scheme = uri.getScheme();
                    if (SCHEME_FILE.equals(scheme)) {
                        mPdfPath = uri.getPath();
                        if (!TextUtils.isEmpty(mPdfPath)) {
                            displayPdfExternal(mPdfPath);
                        }
                    }
                }
            }
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        handleIntent(intent);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (newConfig.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
            iv_rotate.setImageResource(R.drawable.icon_rotate_portrait);
            bg_top.setVisibility(View.VISIBLE);
            bg_bottom.setVisibility(View.VISIBLE);
        } else {
            iv_rotate.setImageResource(R.drawable.icon_rotate_landscape);
            bg_top.setVisibility(View.GONE);
            bg_bottom.setVisibility(View.GONE);
        }
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.rl_back) {
            finish();
        } else if (v.getId() == R.id.rl_last) {
            jumpLast();
        } else if (v.getId() == R.id.rl_next) {
            jumpNext();
        } else if (v.getId() == R.id.ll_send) {
            sendPdf();
        } else if (v.getId() == R.id.ll_rotate) {
            setScreenOrientation();
        }
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        int current = getSeekPage();
        if (current > 0) {
            tv_seek.setText(current + File.separator + mTotalPages);
        }
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        mHandler.removeCallbacksAndMessages(null);
        tv_seek.setVisibility(View.VISIBLE);
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        int current = getSeekPage();
        if (current > 0) {
            jumpTo(current);
        }
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                tv_seek.setVisibility(View.GONE);
            }
        }, 1000);
    }

    private int getSeekPage() {
        if (mTotalPages > 0) {
            int current = (int) ((float) seekBar.getProgress() / 100 * mTotalPages);
            if (current <= mTotalPages && current >= 0) {
                return current;
            }
        }

        return -1;
    }

    private void displayPdfAssets(String assetFileName) {
        mPdfView.fromAsset(assetFileName)
                .defaultPage(0)
                .onTap(this)
                .onPageChange(this)
                .enableAnnotationRendering(true)
                .onLoad(this)
                .scrollHandle(new DefaultScrollHandle(this))
                .spacing(10) // in dp
                .onPageError(this)
                .pageFitPolicy(FitPolicy.BOTH)
                .load();
    }

    private void displayPdfExternal(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {
            mPdfView.fromFile(file)
                    .defaultPage(0)
                    .onPageScroll(this)
                    .onTap(this)
                    .onPageChange(this)
                    .enableAnnotationRendering(true)
                    .onLoad(this)
                    .scrollHandle(new DefaultScrollHandle(this))
                    .spacing(10) // in dp
                    .onPageError(this)
                    .pageFitPolicy(FitPolicy.WIDTH)
                    .load();
        }
    }

    private void displayFromUri(Uri uri) {
        mPdfView.fromUri(uri)
                .defaultPage(0)
                .onPageScroll(this)
                .onTap(this)
                .onPageChange(this)
                .enableAnnotationRendering(true)
                .onLoad(this)
                .scrollHandle(new DefaultScrollHandle(this))
                .spacing(10) // in dp
                .onPageError(this)
                .load();
    }

    private void jumpNext() {
        int current = mPdfView.getCurrentPage();
        jumpTo(++current);
    }

    private void jumpLast() {
        int current = mPdfView.getCurrentPage();
        jumpTo(--current);
    }

    private void jumpTo(int page) {
        jumpTo(page, false);
    }

    private void jumpTo(int page, boolean anim) {
        mPdfView.jumpTo(page, anim);
    }

    private void sendPdf() {
        if (!TextUtils.isEmpty(mPdfPath)) {
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(mPdfPath)));
            intent.setType("application/pdf");

            startActivity(Intent.createChooser(intent, getString(R.string.title_send_pdf)));
        } else {
            Toast.makeText(this, R.string.pdf_no_exist, Toast.LENGTH_SHORT).show();
        }
    }

    private void setScreenOrientation() {
        if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
            //切换竖屏
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        } else {
            //切换横屏
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }
    }

    @Override
    public void onPageChanged(int page, int pageCount) {
        Log.d(TAG, "onPageChanged:" + page + "/" + pageCount);

        if (pageCount > 0) {
            int progress = (int) ((float) page * 100 / pageCount);
            seekBar.setProgress(progress);
        }
    }

    @Override
    public void loadComplete(int nbPages) {
        Log.d(TAG, "loadComplete:" + nbPages);
        tv_title.setText(Utils.getFileName(mPdfPath));
        mTotalPages = nbPages;
        hideTitleAndFooter();
    }

    @Override
    public void onPageError(int page, Throwable t) {
        Log.d(TAG, "onPageError:" + t.getMessage());

        showErrorLayout();
    }

    @Override
    public boolean onTap(MotionEvent e) {
        Log.d(TAG, "onTap ... ");

        if (mTitleBar.getVisibility() == View.VISIBLE) {
            hideTitleAndFooter();
        } else {
            showTitleAndFooter();
        }

        return false;
    }

    @Override
    public void onPageScrolled(int page, float positionOffset) {
        Log.d(TAG, "onPageScrolled ... ");
    }

}
